package aimis.advice;

import aimis.constant.ResponseEnum;
import aimis.dto.Result;
import aimis.exception.AimisException;
import aimis.exception.MyBindException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Profile;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;


@Profile(value = { "dev", "local" })
@RestControllerAdvice("aimis.controller")
public class GlobalExceptionHandlerDev {
	private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandlerProd.class);

	@ExceptionHandler({MethodArgumentNotValidException.class, BindException.class, MyBindException.class, IllegalArgumentException.class})
	public Result methodArgumentNotValidExceptionHandler(Exception e) {
		logger.error("methodArgumentNotValidExceptionHandler", e);
		List<FieldError> fieldErrors = null;
		if (e instanceof MethodArgumentNotValidException) {
			fieldErrors = ((MethodArgumentNotValidException) e).getBindingResult().getFieldErrors();
		}
		if (e instanceof BindException) {
			fieldErrors = ((BindException) e).getBindingResult().getFieldErrors();
		}
		if (e instanceof MyBindException) {
			fieldErrors = ((MyBindException) e).getBindingResult().getFieldErrors();
		}

		if (fieldErrors == null) {
			return Result.error(ResponseEnum.METHOD_ARGUMENT_NOT_VALID);
		}

//        List<String> defaultMessages = new ArrayList<>(fieldErrors.size());
//        for (FieldError fieldError : fieldErrors) {
//            defaultMessages.add(fieldError.getField() + ":" + fieldError.getDefaultMessage());
//        }
		return Result.error(ResponseEnum.METHOD_ARGUMENT_NOT_VALID).setErrors(fieldErrors.stream().collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage))).add("exception",e.getClass()).add("exceptionMsg",e.getMessage());
	}

	@ExceptionHandler({NoSuchElementException.class})
	public Result noSuchElementExceptionHandler(
			NoSuchElementException e) {
		logger.error("noSuchElementExceptionHandler", e);
		return Result.error(ResponseEnum.DATA_NOT_EXIST).add("exception",e.getClass()).add("exceptionMsg",e.getMessage());
	}

	@ExceptionHandler({DataIntegrityViolationException.class})
	public Result dataIntegrityViolationExceptionHandler(
			DataIntegrityViolationException e) {
		logger.error("dataIntegrityViolationException", e);
		return Result.error(ResponseEnum.DATA_FOREIGN_KEY_CONSTRAINT).add("exception",e.getClass()).add("exceptionMsg",e.getMessage());
	}

	@ExceptionHandler({HttpMessageNotReadableException.class})
	public Result methodArgumentNotValidExceptionHandler(
			HttpMessageNotReadableException e) {
		logger.error("methodArgumentNotValidExceptionHandler", e);
		return Result.error(ResponseEnum.HTTP_MESSAGE_NOT_READABLE).add("exception",e.getClass()).add("exceptionMsg",e.getMessage());
	}

	@ExceptionHandler(AimisException.class)
	public Result AimisException(AimisException e) {
		logger.error("AimisExceptionHandler", e);

		ResponseEnum responseEnum = e.getResponseEnum();
		// 失败返回失败消息 + 状态码
		if (responseEnum != null) {
			return Result.error(responseEnum).add("exception", e.getObject());
		}
		// 失败返回消息 状态码固定为直接显示消息的状态码
		return Result.error(e.getMessage()).add("exception",e.getClass()).add("exceptionMsg",e.getMessage());
	}

	@ExceptionHandler(Exception.class)
	public Result exceptionHandler(Exception e) {
		logger.error("exceptionHandler", e);
		return Result.error(ResponseEnum.EXCEPTION).add("exception", e.getClass());
	}
}

